package com.encrypt;

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by huangyugen on 2019/04/30
 **/
public class RSACoder {

    //非对称加密密钥算法
    public static final String KEY_ALGORITHM = "RSA";

    //公钥和私钥
    public static final String PUBLIC_KEY = "RSAPublicKey";
    public static final String PRIVATE_KEY = "RSAPrivateKey";

    //密钥长度，默认1024位，长度必须是64的倍数，范围在512 ~ 65536之间
    public static final int KEY_SIZE = 512;

    /**
     * 私钥解密数据
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] privateKey)throws Exception{
        //取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher instance1 = Cipher.getInstance(keyFactory.getAlgorithm());
        instance1.init(Cipher.DECRYPT_MODE,privateKey1);
        return instance1.doFinal(data);
    }

    /**
     * 公钥解密数据
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data,byte[] publicKey)throws Exception{
        //取得公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
        //对数据解密
        Cipher instance1 = Cipher.getInstance(keyFactory.getAlgorithm());
        instance1.init(Cipher.DECRYPT_MODE,publicKey1);
        return instance1.doFinal(data);
    }
    /**
     * 公钥加密数据
     * @param data
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data,byte[] publicKey)throws Exception{
        //取得公钥
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成公钥
        PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
        //对数据解密
        Cipher instance1 = Cipher.getInstance(keyFactory.getAlgorithm());
        instance1.init(Cipher.ENCRYPT_MODE,publicKey1);
        return instance1.doFinal(data);
    }

    /**
     * 私钥加密数据
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data,byte[] privateKey)throws Exception{
        //取得私钥
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        //生成私钥
        PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //对数据解密
        Cipher instance1 = Cipher.getInstance(keyFactory.getAlgorithm());
        instance1.init(Cipher.ENCRYPT_MODE,privateKey1);
        return instance1.doFinal(data);
    }

    /**
     * 初始化密钥
     * @return
     * @throws Exception
     */
    public static Map<String,Object> initKey()throws Exception{
        //实例化密钥生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        KeyPair keyPair =  keyPairGenerator.generateKeyPair();

        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

        Map<String,Object> map = new HashMap<String, Object>(2);
        map.put(PUBLIC_KEY,publicKey);
        map.put(PRIVATE_KEY,privateKey);
        return map;
    }


    /**
     * 获取publicKey
     * @param keyMap
     * @return
     */
    public static byte[] getPublicKey(Map<String,Object> keyMap){
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return  key.getEncoded();
    }

    /**
     * 获取privateKey
     * @param keyMap
     * @return
     */
    public static byte[] getPrivateKey(Map<String,Object> keyMap){
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return  key.getEncoded();
    }


    public static void main(String[] args) throws Exception {
        //初始化密钥
        Map<String, Object> keyMap = RSACoder.initKey();
        byte[] privateKey = RSACoder.getPrivateKey(keyMap);
        byte[] publicKey = RSACoder.getPublicKey(keyMap);
        System.out.println("【公 钥】："+ Base64.encode(publicKey));
        System.out.println("【私 钥】："+Base64.encode(privateKey));
        System.out.println("=====================================");
        String inputStr = "私钥加密，公钥解密";
        System.out.println("【原 文】："+inputStr);
        byte[] data = RSACoder.encryptByPrivateKey(inputStr.getBytes(), privateKey);
        System.out.println("【加密后】："+Base64.encode(data));
        byte[] str = RSACoder.decryptByPublicKey(data, publicKey);
        System.out.println("【解密后】："+new String(str));

        System.out.println("=====================================");
        String inputStr2 = "公钥加密，私钥解密";
        System.out.println("【原 文】："+inputStr2);
        byte[] data2 = RSACoder.encryptByPublicKey(inputStr2.getBytes(), publicKey);
        System.out.println("【加密后】："+Base64.encode(data2));
        byte[] str2 = RSACoder.decryptByPrivateKey(data2, privateKey);
        System.out.println("【解密后】："+new String(str2));

    }




}
